package com.common.base.widget

import android.animation.TypeEvaluator
import android.animation.ValueAnimator
import android.content.Context
import android.text.TextUtils
import android.util.AttributeSet
import android.view.animation.AccelerateDecelerateInterpolator
import com.common.base.R
import java.math.BigDecimal
import java.math.BigInteger
import java.text.DecimalFormat

/**
 *
 * 作者：sosou
 *
 * 版本：1.0
 *
 * 创建日期：13/2/2023
 *
 * 描述：仿支付宝数字增加
 *
 * 修订历史：
 *
 */
class ShiftyTextview @JvmOverloads constructor(
    context: Context,
    attrs: AttributeSet? = null,
    defStyleAttr: Int = android.R.attr.textViewStyle
) :
    CustomTextView(context, attrs, defStyleAttr) {
    private var mNumStart: String? = "0" // 起始值 默认 0
    private var mNumEnd // 结束值
            : String?
    private var mDuration: Long = 1000 // 动画总时间 默认 1000 毫秒
    private var mPrefixString: String? = "" // 前缀
    private var mPostfixString: String? = "" // 后缀
    private var isEnableAnim = true // 是否开启动画
    private var useCommaFormat //是否使用每三位数字一个逗号的格式，让数字显得比较好看，默认使用
            : Boolean
    private var runWhenChange //是否当内容有改变才使用动画,默认是
            : Boolean
    private var minNum //显示数字最少要达到这个数字才滚动 默认为0.1
            : Float
    var preStr: String? = "0"
    fun setNumberString(number: String) {
        setNumberString("0", number)
    }

    /**
     *
     * @param numberStart
     * @param numberEnd 必须为int或float
     */
    fun setNumberString(numberStart: String, numberEnd: String) {
        mNumStart = numberStart
        mNumEnd = numberEnd
        if (checkNumString(numberStart, numberEnd) && (mNumEnd?:"0.00").toFloat() > minNum) {
            // 数字合法　开始数字动画
            start()
        } else {
            // 数字不合法　直接调用　setText　设置最终值
            text = mPrefixString + numberEnd + mPostfixString
        }
    }

    fun setEnableAnim(enableAnim: Boolean) {
        isEnableAnim = enableAnim
    }

    fun setDuration(mDuration: Long) {
        this.mDuration = mDuration
    }

    fun setPrefixString(mPrefixString: String?) {
        this.mPrefixString = mPrefixString
    }

    fun setPostfixString(mPostfixString: String?) {
        this.mPostfixString = mPostfixString
    }

    fun setMinNumString(minNum: Float) {
        this.minNum = minNum
    }

    fun setUseCommaFormat(useCommaFormat: Boolean) {
        this.useCommaFormat = useCommaFormat
    }

    fun setRunWhenChange(runWhenChange: Boolean) {
        this.runWhenChange = runWhenChange
    }

    private var isInt // 是否是整数
            = false

    init {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.ShiftyTextview)
        mDuration = ta.getInt(R.styleable.ShiftyTextview_duration, 1000).toLong()
        minNum = ta.getFloat(R.styleable.ShiftyTextview_minNum, 0.1f)
        useCommaFormat = ta.getBoolean(R.styleable.ShiftyTextview_useCommaFormat, true)
        runWhenChange = ta.getBoolean(R.styleable.ShiftyTextview_runWhenChange, true)
        isEnableAnim = ta.getBoolean(R.styleable.ShiftyTextview_isEnableAnim, true)
        mNumStart = ta.getString(R.styleable.ShiftyTextview_numStart)
        if (TextUtils.isEmpty(mNumStart)) mNumStart = "0"
        mNumEnd = ta.getString(R.styleable.ShiftyTextview_numEnd)
        if (TextUtils.isEmpty(mNumEnd)) mNumEnd = ""
        mPrefixString = ta.getString(R.styleable.ShiftyTextview_prefixString)
        if (TextUtils.isEmpty(mPrefixString)) mPrefixString = ""
        mPostfixString = ta.getString(R.styleable.ShiftyTextview_postfixString)
        if (TextUtils.isEmpty(mPrefixString)) mPostfixString = ""
        ta.recycle()
    }

    /**
     * 校验数字的合法性
     *
     * @param numberStart 　开始的数字
     * @param numberEnd   　结束的数字
     * @return 合法性
     */
    private fun checkNumString(numberStart: String, numberEnd: String): Boolean {
        val regexInteger = "-?\\d*".toRegex()
        isInt = numberEnd.matches(regexInteger) && numberStart.matches(regexInteger)
        if (isInt) {
            val start = BigInteger(numberStart)
            val end = BigInteger(numberEnd)
            return end.compareTo(start) >= 0
        }
        val regexDecimal = "-?[1-9]\\d*.\\d*|-?0.\\d*[1-9]\\d*".toRegex()
        if ("0" == numberStart) {
            if (numberEnd.matches(regexDecimal)) {
                val start = BigDecimal(numberStart)
                val end = BigDecimal(numberEnd)
                return end.compareTo(start) > 0
            }
        }
        if (numberEnd.matches(regexDecimal) && numberStart.matches(regexDecimal)) {
            val start = BigDecimal(numberStart)
            val end = BigDecimal(numberEnd)
            return end.compareTo(start) > 0
        }
        return false
    }

    private fun start() {
        if (!isEnableAnim) { // 禁止动画
            text = if (useCommaFormat) {
                mPrefixString + format(BigDecimal(mNumEnd)) + mPostfixString
            } else {
                mPrefixString + mNumEnd + mPostfixString
            }
            return
        }
        if (runWhenChange) {
            if (preStr == mNumEnd) {
                //如果两次内容一致，则不做处理
                text = mNumEnd
                return
            }
            preStr = mNumEnd //如果两次内容不一致，记录最新的str
        }
        val animator = ValueAnimator.ofObject(
            BigDecimalEvaluator(),
            BigDecimal(mNumStart),
            BigDecimal(mNumEnd)
        )
        animator.duration = mDuration
        animator.interpolator = AccelerateDecelerateInterpolator()
        animator.addUpdateListener { valueAnimator ->
            val value = valueAnimator.animatedValue as BigDecimal
            text = mPrefixString + format(value) + mPostfixString
        }
        animator.start()
    }

    /**
     * 格式化 BigDecimal ,小数部分时保留两位小数并四舍五入
     *
     * @param bd 　BigDecimal
     * @return 格式化后的 String
     */
    private fun format(bd: BigDecimal): String {
        val pattern = StringBuilder()
        if (isInt) {
            if (useCommaFormat) {
                pattern.append("#,###")
            } else {
                pattern.append("#")
            }
        } else {
            var length = 0

//            val decimals = mNumEnd!!.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }
//                .toTypedArray()[1]
            var decimals = ""
            mNumEnd?.let {numEndIt->
                decimals = numEndIt.split("\\.".toRegex()).dropLastWhile { it.isEmpty() }.toTypedArray()[1]
            }
            length = decimals.length
            if (useCommaFormat) {
                pattern.append("#,##0")
            } else {
                pattern.append("#0")
            }
            if (length > 0) {
                pattern.append(".")
                for (i in 0 until length) {
                    pattern.append("0")
                }
            }
        }
        val df = DecimalFormat(pattern.toString())
        return df.format(bd)
    }

    // 不加 static 关键字，也不会引起内存泄露，因为这里也没有开启线程
    // 加上 static 关键字，是因为该内部类不需要持有外部类的引用，习惯加上
    private class BigDecimalEvaluator : TypeEvaluator<Any?> {
        override fun evaluate(fraction: Float, startValue: Any?, endValue: Any?): Any? {
            val start = startValue as BigDecimal?
            val end = endValue as BigDecimal?
            val result = end?.subtract(start)
            return result?.multiply(BigDecimal("" + fraction))?.add(start)
        }
    }
}